#ifndef GFS_H
#define GFS_H

/* Guest FS: reversed sharing common structures and protocol related header */

#include <stdint.h>

#include "VioSConn.h"
#include "fuse.h"

#define NAME_MAX 255
#define PATH_MAX 4096

#define RETURN_ERROR (-1)
#define RETURN_SUCCESS 0

#define GFS_REQ_NONE 0
#define GFS_REQ_ATTR 1
#define GFS_REQ_OPEN 2
#define GFS_REQ_READ 3
#define GFS_REQ_RDDIR 4
#define GFS_REQ_WRITE 5
#define GFS_REQ_RELEASE 6
#define GFS_REQ_RENAME 7
#define GFS_REQ_REMOVE 8
#define GFS_REQ_TRUNCATE 9
#define GFS_REQ_MKDIR 10
#define GFS_REQ_RMDIR 11

#define GFS_REQ_OP_INVALID(op) (((op) < GFS_REQ_ATTR) || ((op) > GFS_REQ_RMDIR))

#define GFS_SERVER_RECONNECT_DELAY 3000
#define GFS_RECVPKT_IFACE_DELAY 3000
#define GFS_SENDPKT_TOTAL_DELAY 3000

#define REQ_HDR_MAGIC 0x51534647  // GFSQ
#define RPL_HDR_MAGIC 0x52534647  // GFSR

#define RPL_BUFF_MAX (2 * 1024 * 1024)  // 2 MB
#define REQ_BUFF_MAX (2 * 1024 * 1024)  // 2 MB

#define RPL_PATH_ALIGN 8

#define REQ_HDR_SZ sizeof(struct GuestFuseSrvReqHeader)
#define RPL_HDR_SZ sizeof(struct GuestFuseSrvRPLHeader)

// Maximum read size of response
#define RPL_READ_MAX (RPL_BUFF_MAX - sizeof(struct GuestFuseSrvRPLHeader) - \
                      sizeof(struct fuse_in_header) - sizeof(struct fuse_out_header))

// Should be aligned to struct ViosProtoHeader size
struct GuestFuseSrvReqHeader {
    uint32_t magic;
    uint32_t len;
    uint32_t opcode;
    uint32_t rplMaxSize;
    uint64_t opid;
    uint32_t pad[2];
};

struct GuestFuseSrvFileMetaData {
    uint64_t mode;
    uint64_t hostFileHandle;
    uint64_t size;
    int64_t offset;
    // Time of last access.
    int64_t atime;
    // Time of last modification.
    int64_t mtime;
    // Time of last status change.
    int64_t ctime;
    uint32_t pathLen;
    uint32_t padLen;
};

struct GuestFuseSrvReq {
    struct GuestFuseSrvReqHeader hdr;
    struct GuestFuseSrvFileMetaData md;
    char data[1];
};

// Should be aligned to struct ViosProtoHeader size
struct GuestFuseSrvRPLHeader {
    uint32_t magic;
    uint32_t len;
    uint32_t opcode;
    int32_t opret;
    uint64_t opid;
};

struct GuestFuseSrvFile {
    struct GuestFuseSrvFileMetaData md;
    char path[PATH_MAX];
};

struct GuestFuseSrvRPL {
    struct GuestFuseSrvRPLHeader hdr;
    union {
        struct GuestFuseSrvFile file[1];
        char data[1];
    };
};

enum class ConnectionStatus : UINT8 {
    DISCONNECTED,
    CONNECTING,
    CONNECTED,
};

#endif // GFS_H
